"""
视图及逻辑处理工具

"""
import random
from itertools import product

from flask import jsonify, g, request

from models.common import NoRule
from models.order import *
from models.work_order import *

# 1开头的一般为用户模块
code_map = {
    10000: '成功',
    10001: "短信发送失败",
    10002: "请勿重复发送验证码",
    10003: "验证码过期",
    10004: "密码错误",
    100015: "原密码错误",
    10005: "系统错误",
    10006: "没有权限",
    10007: "token过期请重新登录",
    10008: "记录未找到",
    10009: "参数不合法",
    10010: "Mqtt连接失败",
    10011: "未登录",
    10012: "文件未找到",
    10013: "超时",
    10014: "回调失败",
    10016: "接口地址未找到",
}


def resp_with_data(code=None, data=None, msg=None):
    if code != 10000:
        msg = code_map[code]
    if type(data) == dict and 'code' in data.keys() and data['code'] != 10000:
        response = jsonify({'code': data['code'], 'message': data["message"], 'data': data["data"]})
    elif type(msg) == dict:
        response = jsonify({'code': msg['code'], 'message': msg["message"], 'data': msg["data"]})
    else:
        response = jsonify({'code': code, 'message': msg, 'data': data})
    return response


def valid(*pairs):
    """

    参数校验
    :param pairs: (参数, 描述信息)的成对信息
    :return: 返回描述信息，用于抛出异常
    """
    for pair in pairs:
        if not pair[0] and pair[0] not in [True, False]:
            return pair[1]


def get_page(query):
    return {
        'page': g.page,
        'per_page': g.per_page,
        'total': query.count()
    }


def get_tree(model_name, id, vll_id=None):
    ids = list()
    obj = eval(model_name).get_or_none(eval(model_name).id == id)
    ids.append(str(id))
    if not vll_id:
        if obj.parent_id:
            res = get_tree(model_name, obj.parent_id)
            ids += res
    else:
        try:
            son_obj = eval(model_name).get_or_none(eval(model_name).parent_id == id,
                                                   eval(model_name).vll_relation__vll_id == vll_id,
                                                   eval(model_name).vll_relation__is_del == False, )
        except:
            son_obj = None
        if son_obj:
            res = get_tree(model_name, str(son_obj.id), vll_id)
            ids += res
    return ids


def generate_no(model_name, date='', pre_num=-1, **kwargs):
    '''
    生成编号
    :param model_name: 数据表model名称
    :param date: 生成固定日期的编号 2022-10-10
    :param pre_num: 之前编号的数据个数
    :param kwargs:字段参数
    :return:编号
    '''
    # 查找规则数据
    try:
        rule_obj = NoRule.get_or_none(NoRule.model_name ** ('%{}%'.format(model_name)))
    except:
        return ''
    no = []
    for_separate = False
    if model_name in ['Vll', 'LogicPort']:
        for_separate = True

    condition = [eval(model_name).creation_time > 0] if for_separate else \
        [eval(model_name).create_time > '1970-01-01']
    # condition.append(eval(model_name).is_del == F)
    # 是否需要做删除过滤？
    # condition = {'is_del': 0}
    for rule in rule_obj.rule.split('+'):
        import time
        if rule.startswith('%') and rule.endswith('%'):
            rule = rule[1:-1].split(':')
            if rule[0] == 'time':
                if date:
                    rule = time.strftime(rule[1], time.strptime(date, '%Y-%m-%d'))
                    today = time.strftime('%Y-%m-%d', time.strptime(date, '%Y-%m-%d'))
                else:
                    rule = time.strftime(rule[1], time.localtime(time.time()))
                    today = time.strftime('%Y-%m-%d', time.localtime(time.time()))
                condition.append(eval(model_name).creation_time > today) if for_separate else \
                    condition.append(eval(model_name).create_time > today)
            elif rule[0].startswith('field'):
                field = rule[0].split('-')[-1]
                if ',' in rule[1]:
                    con_list = rule[1].split(',')
                    for epr in con_list:
                        # 支持 =
                        if '=' in epr:
                            con, val = epr.split('=')
                            # 支持in 多个值用&隔开
                            # d2d&c2c&d2c=B
                            if '&' in con:
                                in_con = con.split('&')
                                if kwargs.get(field) in in_con:
                                    condition.append(eval(model_name).field in in_con)
                                    rule = val
                            else:
                                if kwargs.get(field) == con:
                                    if kwargs.get(field) != 'port':
                                        condition.append(eval(model_name).type == kwargs.get(field))
                                    rule = val
                    # 最后一个结果为默认值
                    if type(rule) == list:
                        rule = ''
                        condition.append(eval(model_name).field == kwargs.get(field))
                else:
                    rule = rule[1]
            elif rule[0] == 'auto':
                if pre_num == -1:
                    if for_separate:
                        pre_data = eval(model_name).select().where(*condition).order_by(
                            eval(model_name).no.desc())
                    else:
                        pre_data = eval(model_name).select().where(*condition).order_by(
                            eval(model_name).create_time.desc())
                    if pre_data:
                        try:
                            pre_num = int(pre_data[0].no[-int(rule[1]):])
                        except:
                            pre_num = 0
                    else:
                        pre_num = 0
                rule = str(pre_num + 1).zfill(int(rule[1]))
            else:
                rule = ''
        no.append(rule)
    return ''.join(no)


def create_verify_code(count=6, type='number'):
    if type == 'number':
        str_lib = '1234567890'
    else:
        str_lib = '1234567890abcdefghijklmnopqrstuvwxyz!@#$%^&*()'
    return ''.join(random.sample(str_lib, count))


def flatten_dict(data, parent_key='', sep='*'):
    flattened_dict = {}
    for key, value in data.items():
        new_key = f"{parent_key}{sep}{key}" if parent_key else key
        if isinstance(value, dict):
            # 递归处理嵌套字典
            flattened_dict.update(flatten_dict(value, new_key, sep=sep))
        else:
            flattened_dict[new_key] = value
    return flattened_dict


def save_all_nos(model_name, date_list=None):
    '''
    重新保存编号方法
    :param model_name: 数据表model名称
    :param date_list: 列表 某天/某些天的编号重新排布 ["2022-08-16","2022-10-10]
    :return:
    '''
    try:
        rule_obj = NoRule.get_or_none(NoRule.model_name ** ('%{}%'.format(model_name)))
    except:
        return
    # 判断编号是否携带时间
    if "%time:" in rule_obj.rule:
        with_date = True
    else:
        with_date = False
    # 判断编号是否携带根据字段分别编号以及处理字段编号规则
    field_con = ''
    if "%field-" in rule_obj.rule:
        with_field = True
        for i in rule_obj.rule.split('+'):
            if i.startswith('%field-'):
                field_con = i.replace('%', '')
    else:
        with_field = False
    condition = {'create_time__gt': '1970-01-01'}
    # 携带时间数据处理
    if with_date:
        if date_list:
            condition['create_time__date__in'] = date_list
        else:
            query = (NoRule
                     .select(fn.DATE(NoRule.create_time).alias('day'), fn.COUNT(NoRule.id).alias('count'))
                     .group_by(fn.DATE(NoRule.create_time))
                     .order_by(fn.DATE(NoRule.create_time)))
            date_list = [row.day for row in query]

    # 处理字段名称与编号在字段规则下的存储值
    field = ''
    con_list = []
    field_val_list = []
    if with_field and field_con:
        field, con_list = field_con.split(':')
        if ',' in con_list:
            field = field.split('-')[-1]
            con_list = con_list.split(',')
            field_val_list = [i.split('=')[-1] for i in field_con.split(',')]
    # 定义数量字典
    n_dict_list = [[model_name]]
    if with_date and date_list:
        n_dict_list.append(date_list)
    if field_val_list:
        n_dict_list.append(field_val_list)
    n_dict_list = list(product(*n_dict_list))
    n_dict = {('_').join(i): 0 for i in n_dict_list}
    # 查询数据
    datas = eval(model_name).select().where(**condition).order_by('create_time')
    if datas:
        for data in datas:
            data_date = ''
            kwargs = {}
            data_dict = model_to_dict(data)
            key_list = [model_name]
            # 如果携带日期 字典键拼接日期
            if with_date:
                data_date = data.create_time.strftime('%Y-%m-%d')
                key_list.append(data_date)
            # 如果携带根据字段编号规则，字典键拼接规则值，并传递字段参数
            if with_field and field_con:
                for epr in con_list:
                    if '=' in epr:
                        con, val = epr.split('=')
                        # 布尔类型转成 '0' / '1'
                        if type(data_dict[field]) == bool:
                            data_dict[field] = str(int(data_dict[field]))
                        # 支持in 多个值用&隔开
                        # d2d&c2c&d2c=B
                        if '&' in con:
                            in_con = con.split('&')
                            if data_dict[field] in in_con:
                                key_list.append(str(val))
                                kwargs[field] = data_dict[field]
                        # 支持 =
                        else:
                            if data_dict[field] == con:
                                key_list.append(str(val))
                                kwargs[field] = data_dict[field]
            key = '_'.join(key_list)
            no = generate_no(model_name, date=data_date, pre_num=n_dict[key], **kwargs)
            n_dict[key] += 1
            data.no = no
            data.save()
    return 'finish'


def rewrite_request(method, args=None, data=None, headers=None):
    # 请求方式重写
    request.method = method
    # 参数重写
    # 重写args参数
    if args:
        request.args = args
    # 重写data参数，仅支持json格式
    if data:
        request.data = data
